package com.sxt.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;

/**
 * @模块目的/功能：TCPServer服务器端 
 * @版权说明： 
 * @版本号：1.0
 * @日期：2019.11.13
 * @作者：罗林
 */
@Slf4j
public class TCPServer {
	
	private volatile boolean isRunning = false;
	// 端口号
	private Integer port;
	//
	private byte delimiter;
	//主线程组
	private EventLoopGroup bossGroup = null;
	//工作线程组
	private EventLoopGroup workerGroup = null;

	/**
	 * @函数的名称:TCPServer
	 * @目的/功能:无参构造函数
	 * @输入参数:无
	 * @返回值:无
	 * @作者:罗林
	 * @日期:2019.11.13
	 */
	public TCPServer() {

	}

	public TCPServer(int port, byte delimiter) {
		
		this.port = port;
		
		this.delimiter = delimiter;
	}
	/**
	 * @函数的名称:startServer
	 * @目的/功能:启动服务器
	 * @输入参数:无
	 * @返回值:无
	 * @作者:罗林
	 * @日期:2019.11.13
	 */
	public synchronized void startServer() {
		if (this.isRunning) {
            throw new IllegalStateException(this.getName() + " is already started .");
        }
        this.isRunning = true;

        new Thread(() -> {
            try {
                this.bind();
            } catch (Exception e) {
                log.info("TCP服务启动出错:{}", e.getMessage());
                e.printStackTrace();
            }
        }, this.getName()).start();
	}
	/**
	 * @函数的名称:stopServer
	 * @目的/功能:停止服务器
	 * @输入参数:无
	 * @返回值:无
	 * @作者:罗林
	 * @日期:2019.11.13
	 */
	public synchronized void stopServer() {
		if (!this.isRunning) {
            throw new IllegalStateException(this.getName() + " is not yet started .");
        }
        this.isRunning = false;

        try {
            Future<?> future = this.workerGroup.shutdownGracefully().await();
            if (!future.isSuccess()) {
                log.error("workerGroup 无法正常停止:{}", future.cause());
            }

            future = this.bossGroup.shutdownGracefully().await();
            if (!future.isSuccess()) {
                log.error("bossGroup 无法正常停止:{}", future.cause());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info("TCP服务已经停止...");
	}
	
	private String getName() {
        return "TCP-Server";
    }
	
	
	private void bind() throws Exception {
		/** 针对linux优化 */
		String osName = System.getProperty("os.name");
		/** 配置服务端的NIO线程组 */
		if (osName.equalsIgnoreCase("Linux")) {
			/** 负责服务端接收客户端的连接 */
			this.bossGroup = new EpollEventLoopGroup();
			/** 负责进行SocketChannel的网络读写 */
			this.workerGroup = new EpollEventLoopGroup();
		} else {
			/** 负责服务端接收客户端的连接 */
			this.bossGroup = new NioEventLoopGroup();
			/** 负责进行SocketChannel的网络读写 */
			this.workerGroup = new NioEventLoopGroup();
		}
		/** Netty启动Nio服务端的辅助类 */
		ServerBootstrap bootstrap = new ServerBootstrap();

		bootstrap.group(this.bossGroup, this.workerGroup)
				// keepAlive默认是打开
				.option(ChannelOption.SO_KEEPALIVE, true)// 保持连接
				.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) //
				.option(ChannelOption.SO_SNDBUF, 1024 * 256) // 发包缓冲区，单位多少？
				.option(ChannelOption.SO_RCVBUF, 1024 * 256) // 收包缓冲区，单位多少？
				.option(ChannelOption.TCP_NODELAY, true); // TCP立即发包
		/** Linux平台用Epoll模式 **/
		if (osName.equals("Linux")) { // Linux平台用Epoll模式
			bootstrap.channel(EpollServerSocketChannel.class);
		} else {
			bootstrap.channel(NioServerSocketChannel.class);
		}

		/** 添加解码器、编码器 */

		bootstrap.childHandler(new MsgCoderHandler(this.delimiter));

		try {
			/** 绑定端口同步操作 */
			ChannelFuture future = bootstrap.bind(this.port).sync();
			/** 监听端口关闭(//等待客户端链路关闭) **/
			future.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			/** 优雅退出,释放资源 */
			// 关闭工作线程组
			this.workerGroup.shutdownGracefully();
			// 关闭主线程组
			this.bossGroup.shutdownGracefully();
		}

	}
}
